今天的實作有點兒難度,是要用到你的視訊鏡頭,做出一個能夠製造特效、拍照及下載的功能,介面如下:
每拍一張照,下方就會多一張照片,點選即可下載該張照片。
但由於視訊鏡頭牽涉到安全性問題,需要用到https,這邊就不提供實作範例。有興趣的同學可直接下載教材試用。
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
    .then(localMediaStream => {
      video.srcObject = localMediaStream;
      video.play();
    })
function paintToCanvas() {
    const width = video.videoWidth;
    const height = video.videoHeight;
    canvas.width = width;
    canvas.height = height;
    return setInterval(() => {
        ctx.drawImage(video, 0, 0, width, height);
    }, 16);
}
將視訊鏡頭的解析度同樣設定給畫布,而下方的setInterval()是為了讓畫布能夠和鏡頭同步(若沒設定的話畫布就不會動),根據可負荷效能來調整每多少毫秒要更新畫面一次。function takePhoto() {
  // played the sound
  snap.currentTime = 0;
  snap.play();
  // take the data out of the canvas
  const data = canvas.toDataURL('image/jpeg');
  const link = document.createElement('a');
  link.href = data;
  link.setAttribute('download', 'handsome');
  link.innerHTML = `<img src="${data}" alt="Handsome Man" />`;
  strip.insertBefore(link, strip.firsChild);
}
前面snap部分是播放相機快門聲。後面是產生一個下載連結,並以相片的方式呈現。最後insertBefore()是為了將每次新拍的照片都出現在列表最前面。function rgbSplit(pixels) {
  for (let i = 0; i < pixels.data.length; i+=4) {
    pixels.data[i - 150] = pixels.data[i + 0]; // RED
    pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
    pixels.data[i - 550] = pixels.data[i + 2]; // Blue
  }
  return pixels;
}
首先要做特效必須先將畫布的像素抓出來let pixels = ctx.getImageData(0, 0, width, height),調整完後再放回去ctx.putImageData(pixels, 0, 0);。而pixels其實是超大一串由紅、綠、藍、透明度四個數輪流組成的Array(影像每個像素是由RGB組成,每個顏色範圍為0~255,透明度則是0~1)。這個特效的概念很簡單,就只是分別給予紅綠藍不同的差值,例如上面例子就是將迴圈目前像素的紅光值填進前面150個像素位置,把綠光值填近後面第500個像素位置,藍光值填進前面550個像素位置。所以三個顏色就會產生平移的偏差,造成圖片中的效果。